#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
仪表操作控制器
从CalibrationThread中分离出的仪表操作与读取功能，供校准和验证过程复用
"""

import time
import logging
from typing import Dict, Optional, Tuple
from PyQt5.QtCore import QObject, pyqtSignal

from instruments.sa import KeysightSignalAnalyzer, RSSignalAnalyzer
from instruments.sg import KeysightSignalGenerator, RSSignalGenerator


class InstrumentController(QObject):
    """仪表操作控制器
    
    封装了对信号源(SG)、频谱仪(SA)和衰减器的标准操作流程，
    提供一致的接口供校准和验证过程使用。
    """
    
    # 信号定义
    log_signal = pyqtSignal(str)  # 日志信息信号
    
    def __init__(self, parent=None):
        super().__init__(parent)
        
        # 仪器实例
        self.sg = None          # 信号源
        self.sa = None          # 频谱仪
        self.attenuator = None  # 数字衰减器
        
        # 仪器参数配置
        self.current_freq = 0
        self._instruments_initialized = False
        
    def initialize_instruments(self, sg_widget, sa_widget, attenuator) -> bool:
        """初始化所有仪器
        
        Args:
            sg_widget: 信号源控件，包含型号和地址信息
            sa_widget: 频谱仪控件，包含型号和地址信息  
            attenuator: 数字衰减器实例
            
        Returns:
            bool: 初始化是否成功
        """
        try:
            # 保存衰减器引用
            self.attenuator = attenuator
            
            # 初始化信号源
            if not self._initialize_signal_generator(sg_widget):
                return False
                
            # 初始化频谱仪
            if not self._initialize_signal_analyzer(sa_widget):
                return False
            
            self._instruments_initialized = True
            self.log_signal.emit("仪器初始化完成")
            return True
            
        except Exception as e:
            logging.error(f"仪器初始化失败: {str(e)}")
            self.log_signal.emit(f"仪器初始化失败: {str(e)}")
            return False
    
    def _initialize_signal_generator(self, sg_widget) -> bool:
        """初始化信号源"""
        try:
            sg_model = sg_widget.instrument_model_combobox.currentText()
            sg_address = sg_widget.vias_address_editer.text()
            
            if sg_model == 'Keysight':
                self.sg = KeysightSignalGenerator(sg_address)
            else:
                self.sg = RSSignalGenerator(sg_address)
                
            if not self.sg.connect():
                raise Exception("信号源连接失败")
                
            self.log_signal.emit(f"信号源初始化成功: {sg_model} @ {sg_address}")
            return True
            
        except Exception as e:
            self.log_signal.emit(f"信号源初始化失败: {str(e)}")
            return False
    
    def _initialize_signal_analyzer(self, sa_widget) -> bool:
        """初始化频谱仪"""
        try:
            sa_model = sa_widget.instrument_model_combobox.currentText()
            sa_address = sa_widget.vias_address_editer.text()
            
            if sa_model == 'Keysight':
                self.sa = KeysightSignalAnalyzer(sa_address)
            else:
                self.sa = RSSignalAnalyzer(sa_address)
                
            if not self.sa.connect():
                raise Exception("频谱仪连接失败")
                
            self.log_signal.emit(f"频谱仪初始化成功: {sa_model} @ {sa_address}")
            return True
            
        except Exception as e:
            self.log_signal.emit(f"频谱仪初始化失败: {str(e)}")
            return False
    
    def setup_sa_basic_config(self):
        """设置频谱仪基本配置（用于校准流程）"""
        if not self.sa:
            raise RuntimeError("频谱仪未初始化")
            
        try:
            self.sa.preset()
            self.sa.set_detector('POSITIVE')
            self.sa.set_trace_type("MAXHOLD")
            self.log_signal.emit("频谱仪基本配置完成")
        except Exception as e:
            self.log_signal.emit(f"频谱仪基本配置失败: {str(e)}")
            raise
    
    def setup_measurement_parameters(self, frequency: float, att_value: float, 
                                   rbw_1: str, vbw_1: str, span_1: str,
                                   rbw_2: str, vbw_2: str, span_2: str) -> float:
        """设置测量参数并返回信号源电平
        
        Args:
            frequency: 频率 (MHz)
            att_value: 衰减器值 (dB)
            rbw_1: 低频段分辨率带宽
            vbw_1: 低频段视频带宽
            span_1: 低频段频率宽度
            rbw_2: 高频段分辨率带宽  
            vbw_2: 高频段视频带宽
            span_2: 高频段频率宽度
            
        Returns:
            float: 设置的信号源电平 (dBm)
        """
        if not self._instruments_initialized:
            raise RuntimeError("仪器未初始化")
        
        try:
            # 1. 设置衰减器值
            self.attenuator.set_att(att_value)
            self.log_signal.emit(f"设置衰减器值: {att_value} dB")
            
            # 2. 根据衰减器值调整信号源输出和频谱仪参数
            sg_level = min(max(att_value, 0), 17)  # Level调节范围限定为0至17
            
            if att_value >= 50:
                self.sa.set_att(0)
                self.sa.set_ref_level(-35)
                sg_level = 15
            else:
                self.sa.set_att(20)
                self.sa.set_ref_level(10)
                sg_level = 0
                
            self.sg.set_amplitude(sg_level)
            self.sg.set_rf(1)
            self.log_signal.emit(f"设置信号源输出: {sg_level} dBm")
            
            # 3. 设置信号源频率
            self.sg.set_frequency(f"{frequency} MHz")
            self.current_freq = frequency
            
            # 4. 根据频率设置频谱仪参数
            if frequency < 1000:  # < 1GHz
                self.sa.set_rbw(rbw_1)
                self.sa.set_vbw(vbw_1)
                self.sa.set_span(span_1)
            else:  # >= 1GHz
                self.sa.set_rbw(rbw_2)
                self.sa.set_vbw(vbw_2)
                self.sa.set_span(span_2)
            
            # 5. 高衰减时调整频谱仪参数
            # if att_value >= 70:
            #     self.sa.set_rbw('10 kHz')
            #     self.sa.set_vbw('30 kHz')
            
            # 6. 设置频谱仪中心频率和扫描时间
            self.sa.set_sweep_time('50 ms')
            self.sa.set_frequency(f"{frequency} MHz")
            
            # 7. 等待稳定并重启扫描
            self.sa.restart()
            time.sleep(0.5)
            self.sa.restart()
            time.sleep(0.1)
            
            return sg_level
            
        except Exception as e:
            self.log_signal.emit(f"设置测量参数失败: {str(e)}")
            raise
    
    def measure_power(self) -> float:
        """测量功率值
        
        Returns:
            float: 测量的功率值 (dBm)
        """
        if not self.sa:
            raise RuntimeError("频谱仪未初始化")
            
        try:
            # 设置标记并测量功率
            self.sa.xapp_connectivity_set_sa_peak_status(1, 1)
            self.sa.set_mark_frequency_or_time(1, f"{self.current_freq} MHz")
            power = self.sa.get_mark_power(1)
            
            self.log_signal.emit(f"测量功率: {power:.2f} dBm @ {self.current_freq} MHz")
            return power
            
        except Exception as e:
            self.log_signal.emit(f"测量功率时出错: {str(e)}")
            raise
    
    def perform_complete_measurement(self, frequency: float, att_value: float,
                                   rbw_1: str, vbw_1: str, span_1: str,
                                   rbw_2: str, vbw_2: str, span_2: str) -> Tuple[float, float]:
        """执行完整的测量流程
        
        Args:
            frequency: 频率 (MHz)
            att_value: 衰减器值 (dB)
            rbw_1: 低频段分辨率带宽
            vbw_1: 低频段视频带宽
            span_1: 低频段频率宽度
            rbw_2: 高频段分辨率带宽
            vbw_2: 高频段视频带宽
            span_2: 高频段频率宽度
            
        Returns:
            Tuple[float, float]: (信号源电平, 测量功率)
        """
        # 设置测量参数
        sg_level = self.setup_measurement_parameters(
            frequency, att_value, rbw_1, vbw_1, span_1, rbw_2, vbw_2, span_2)
        
        # 测量功率
        measured_power = self.measure_power()
        if measured_power < -70:
            time.sleep(1)
            measured_power = self.measure_power()
        
        return sg_level, measured_power
    
    def setup_verification_mode(self, sg_power: float = 0.0):
        """设置验证模式的仪器参数
        
        Args:
            sg_power: 信号源输出功率 (dBm)
        """
        if not self._instruments_initialized:
            raise RuntimeError("仪器未初始化")
            
        try:
            # 设置信号源
            if self.sg:
                self.sg.set_amplitude(sg_power)
                self.sg.set_rf(1)  # 开启输出
                self.log_signal.emit(f"验证模式 - 信号源设置: {sg_power} dBm")
            
            # 设置频谱仪基本参数
            if self.sa:
                self.sa.preset()
                self.sa.set_detector('POSITIVE')
                self.sa.set_trace_type("MAXHOLD")
                self.sa.set_span("0 MHz")  # 零频率宽度
                self.sa.set_ref_level(sg_power + 10)  # 参考电平
                self.log_signal.emit("验证模式 - 频谱仪初始化完成")
                
        except Exception as e:
            self.log_signal.emit(f"验证模式设置失败: {str(e)}")
            raise
    
    def perform_verification_measurement(self, frequency: float, 
                                       theoretical_compensation: float) -> Optional[float]:
        """执行验证测量
        
        Args:
            frequency: 频率 (MHz)
            theoretical_compensation: 理论补偿值 (dB)
            
        Returns:
            Optional[float]: 测量功率，失败时返回None
        """
        if not self._instruments_initialized:
            raise RuntimeError("仪器未初始化")
            
        try:
            # 设置衰减器为理论补偿值
            self.attenuator.set_att(theoretical_compensation)
            self.log_signal.emit(f"设置衰减器: {theoretical_compensation:.2f} dB")
            
            # 设置信号源和频谱仪频率
            self.sg.set_frequency(f"{frequency} MHz")
            self.sa.set_frequency(f"{frequency} MHz")
            self.current_freq = frequency

            self.sa.set_att(20)
            self.sa.set_ref_level(10)


            self.sg.set_amplitude(0)
            self.sg.set_rf(1)
            # self.log_signal.emit(f"设置信号源输出: {sg_level} dBm")

            # 3. 设置信号源频率
            self.sg.set_frequency(f"{frequency} MHz")
            self.current_freq = frequency

            # 4. 根据频率设置频谱仪参数
            if frequency < 1000:  # < 1GHz
                self.sa.set_rbw('100 kHz')
                self.sa.set_vbw('200 kHz')
                self.sa.set_span("0 MHz")
            else:  # >= 1GHz
                self.sa.set_rbw('1 MHz')
                self.sa.set_vbw('3 MHz')
                self.sa.set_span("0 MHz")

            # 5. 高衰减时调整频谱仪参数
            # if att_value >= 70:
            #     self.sa.set_rbw('10 kHz')
            #     self.sa.set_vbw('30 kHz')

            # 6. 设置频谱仪中心频率和扫描时间
            self.sa.set_sweep_time('50 ms')
            
            # 等待稳定
            time.sleep(0.5)
            
            # 测量功率
            measured_power = self.measure_power()
            return measured_power
            
        except Exception as e:
            self.log_signal.emit(f"验证测量失败: {str(e)}")
            return None
    
    def shutdown_instruments(self):
        """关闭仪器输出"""
        try:
            if self.sg:
                self.sg.set_rf(0)
                self.log_signal.emit("信号源输出已关闭")
        except Exception as e:
            self.log_signal.emit(f"关闭仪器时出错: {str(e)}")
    
    def get_reference_loss(self, frequency: float, reference_loss_data: Dict) -> float:
        """获取指定频率的参考线线损
        
        Args:
            frequency: 频率值
            reference_loss_data: 参考线损数据字典
            
        Returns:
            float: 参考线线损值
        """
        if not reference_loss_data:
            return 0.0
            
        try:
            # 将频率转换为字符串格式
            freq_str = str(float(frequency))
            
            # 直接查找
            if freq_str in reference_loss_data:
                return float(reference_loss_data[freq_str])
            
            # 如果没有直接匹配，找最接近的频率点
            frequencies = [float(f) for f in reference_loss_data.keys()]
            closest_freq = min(frequencies, key=lambda x: abs(x - float(frequency)))
            
            return float(reference_loss_data[str(closest_freq)])
            
        except Exception as e:
            self.log_signal.emit(f'获取参考线线损失败: {str(e)}')
            return 0.0
    
    def calculate_actual_attenuation(self, sg_level: float, measured_value: float,
                                   reference_loss: float) -> Tuple[float, float]:
        """计算真实衰减值
        
        Args:
            sg_level: 信号源电平 (dBm)
            measured_value: 测量值 (dBm)
            reference_loss: 参考线线损 (dB)
            
        Returns:
            Tuple[float, float]: (补偿后测量值, 真实衰减值)
        """
        # 从测量值中减去参考线线损（注意：线损为负值，所以实际上是加上绝对值）
        compensated_value = measured_value - reference_loss
        
        # 计算真实的衰减值：信号源输出功率 - 补偿后的测量值
        actual_attenuation = sg_level - compensated_value
        
        # 四舍五入到两位小数
        compensated_value = round(compensated_value, 2)
        actual_attenuation = round(actual_attenuation, 2)
        
        return compensated_value, actual_attenuation
    
    @property
    def is_initialized(self) -> bool:
        """检查仪器是否已初始化"""
        return self._instruments_initialized